
import requests
from bs4 import BeautifulSoup

class YoudaoDictScraper:
    def __init__(self):
        self.base_url = "https://dict.youdao.com/result?word={word}&lang=en"
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }

    def get_word_info(self, word):
        """获取单词信息的API，返回格式与v2.xxapi.cn一致"""
        url = self.base_url.format(word=word)
        response = requests.get(url, headers=self.headers)
        
        if response.status_code != 200:
            return self._build_error_response(response.status_code)
        
        soup = BeautifulSoup(response.text, 'html.parser')
        word_data = self._extract_word_data(soup, word)
        
        return self._build_success_response(word_data)

    def _build_error_response(self, status_code):
        """构建错误响应"""
        return {
            "code": status_code,
            "msg": f"请求失败: {status_code}",
            "data": None,
            "request_id": self._generate_request_id()
        }

    def _build_success_response(self, word_data):
        """构建成功响应"""
        return {
            "code": 200,
            "msg": "数据请求成功",
            "data": word_data,
            "request_id": ""
        }



    def _extract_word_data(self, soup, word):
        """提取单词数据"""
        return {
            "bookId": "YOUDAO_DICT",
            "word": word,
            **self._extract_pronunciation(soup),
            **self._extract_translations_and_examples(soup)
        }

    def _extract_pronunciation(self, soup):
        """提取音标和发音"""
        pronunciation = {
            "ukphone": "",
            "ukspeech": "",
            "usphone": "", 
            "usspeech": ""
        }
        
        phonetics = soup.find_all('span', class_='phonetic')
        if phonetics:
            pronunciation["ukphone"] = phonetics[0].get_text(strip=True) if len(phonetics) > 0 else ""
            pronunciation["usphone"] = phonetics[1].get_text(strip=True) if len(phonetics) > 1 else ""
        
        keyword = soup.find('div', class_='keyword')
        if keyword:
            word = keyword.get_text(strip=True)
            pronunciation["ukspeech"] = f"https://dict.youdao.com/dictvoice?audio={word}&type=1"
            pronunciation["usspeech"] = f"https://dict.youdao.com/dictvoice?audio={word}&type=2"
        
        return pronunciation

    def _extract_translations_and_examples(self, soup):
        """提取翻译、例句、短语和相关词汇"""
        return {
            "phrases": self._extract_phrases(soup),
            "relWords": self._extract_related_words(soup),
            "sentences": self._extract_sentences(soup),
            "synonyms": self._extract_synonyms(soup),
            "translations": self._extract_translations(soup)
        }

    def _extract_phrases(self, soup):
        """提取短语"""
        phrases = []
        phrase_container = soup.find('div', class_='webPhrase')
        
        if phrase_container:
            for item in phrase_container.find_all('li', class_='mcols-layout'):
                point = item.find('a', class_='point')
                sen_phrase = item.find('p', class_='sen-phrase')
                if point and sen_phrase:
                    phrases.append({
                        "p_cn": sen_phrase.get_text(strip=True),
                        "p_content": point.get_text(strip=True)
                    })
        
        return phrases if phrases else []

    def _extract_related_words(self, soup):
        """提取相关词汇"""
        rel_words = []
        word_forms_container = soup.find('div', class_='word-forms')
        
        if word_forms_container:
            for item in word_forms_container.find_all('li', class_='word-wfs-cell-less'):
                wfs_name = item.find('span', class_='wfs-name')
                transformation = item.find('span', class_='transformation')
                if wfs_name and transformation:
                    rel_words.append({
                        "Hwds": [{
                            "hwd": transformation.get_text(strip=True),
                            "tran": f" {wfs_name.get_text(strip=True)}形式"
                        }],
                        "Pos": "n"
                    })
        
        return rel_words if rel_words else []

    def _extract_sentences(self, soup):
        """提取例句"""
        sentences = []
        example_container = soup.find('div', id='catalogue_sentence')
        
        if example_container:
            sents_part = example_container.find('div', class_='blng_sents_part')
            if sents_part:
                for item in sents_part.find_all('li', class_='mcols-layout'):
                    sen_eng = item.find('div', class_='sen-eng')
                    sen_ch = item.find('div', class_='sen-ch')
                    if sen_eng and sen_ch:
                        sentences.append({
                            "s_cn": sen_ch.get_text(strip=True),
                            "s_content": sen_eng.get_text(strip=True)
                        })
        
        return sentences if sentences else []

    def _extract_synonyms(self, soup):
        """提取同义词"""
        synonyms = []
        # 有道词典的同义词可能在特定结构中，这里需要根据实际网页结构调整
        # 以下是一个可能的查找逻辑示例
        synonym_container = soup.find('div', class_='synonyms')
        if synonym_container:
            for item in synonym_container.find_all('li'):
                word = item.find('a')
                if word:
                    synonyms.append({
                        "Hwds": [{"word": word.get_text(strip=True)}],
                        "pos": "n",
                        "tran": ""
                    })
        
        return synonyms if synonyms else []

    def _extract_translations(self, soup):
        """提取翻译"""
        translations = []
        simple_module = soup.find('div', class_='simple dict-module')
        
        if simple_module:
            trans_container = simple_module.find('div', class_='trans-container')
            if trans_container:
                for exp in trans_container.find_all('li', class_='word-exp'):
                    pos = exp.find('span', class_='pos')
                    trans = exp.find('span', class_='trans')
                    if pos and trans:
                        pos_text = pos.get_text(strip=True)[0].lower() if pos.get_text(strip=True) else "n"
                        translations.append({
                            "pos": "v" if pos_text.startswith('v') else "n",
                            "tran_cn": trans.get_text(strip=True)
                        })
        
        return translations if translations else []
